package com.smartlink.vn.digitalsignaturetool;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

public class DigitalSignatureTool {

    private String signatureAlgorith;
    private String certificateType;

    public DigitalSignatureTool() {
        this.signatureAlgorith = "SHA1withRSA";
        this.certificateType = "X.509";
    }

    public boolean verify(String filePath, String signedFilePath, String cerFilePath) throws FileNotFoundException, CertificateException, IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException {
        FileInputStream fis = new FileInputStream(cerFilePath);
        BufferedInputStream bis = new BufferedInputStream(fis);

        CertificateFactory cf = CertificateFactory.getInstance(certificateType);
        Certificate cert;
        PublicKey publicKey = null;
        while (bis.available() > 0) {
            cert = cf.generateCertificate(bis);
            publicKey = cert.getPublicKey();
        }
        bis.close();
        fis.close();

        byte[] signedFile = IOUtils.toByteArray(new FileInputStream(signedFilePath));
        byte[] signedFile64 = Base64.decodeBase64(signedFile);
        byte[] file = IOUtils.toByteArray(new FileInputStream(filePath));

        Signature sig = Signature.getInstance(signatureAlgorith);
        sig.initVerify(publicKey);
        sig.update(file, 0, file.length);
        boolean verify = sig.verify(signedFile64);
        return verify;
    }

    public String getSignatureAlgorith() {
        return signatureAlgorith;
    }

    public void setSignatureAlgorith(String signatureAlgorith) {
        this.signatureAlgorith = signatureAlgorith;
    }

    public String getCertificateType() {
        return certificateType;
    }

    public void setCertificateType(String certificateType) {
        this.certificateType = certificateType;
    }

    public static void main(String[] args) throws Exception {
        if (args.length != 3) {
            throw new Exception("Invalid args. args length = 3. args[0]: file to verify. args[1]: signed file. args[2]: cert file.");
        }
        DigitalSignatureTool tool = new DigitalSignatureTool();
        boolean result = tool.verify(args[0], args[1], args[2]);
        System.out.println(result);
    }

}
